#include "game.h"

int _game_draw_sort_sprites(const void *a, const void *b);
void _game_draw_frame(Game *game, int localPlayerIndex, int playerIndex, Game_Entity *sortedEntities);

int _game_draw_sort_sprites(const void *a, const void *b)
{
    const Game_Entity *e1 = a;
    const Game_Entity *e2 = b;
    return e1->y - e2->y;
}

void _game_draw_frame(Game *game, int localPlayerIndex, int playerIndex, Game_Entity *entities)
{
    int dx = 0, dy = 0;
    int centerX = 0, centerY = 0;
    int scrX, scrY, scrW, scrH;
    if(playerIndex >= 0)
    {
        dx = -game->players[playerIndex].camX;
        dy = -game->players[playerIndex].camY;

        // Single player
        if(array_size(game->localPlayers) == 1)
        {
            centerX = VSCREEN_WIDTH/2;
            centerY = VSCREEN_HEIGHT/2;
            scrX = scrY = 0;
            scrW = VSCREEN_WIDTH;
            scrH = VSCREEN_HEIGHT;
        }

        // 2 player splitscreen
        else if(array_size(game->localPlayers) == 2)
        {
            centerX = VSCREEN_WIDTH/2;
            centerY = VSCREEN_HEIGHT/4;
            if(localPlayerIndex == 0)
            {
                scrX = scrY = 0;
                scrW = VSCREEN_WIDTH;
                scrH = VSCREEN_HEIGHT/2;
                gfx_clipping_set(0, 0, VSCREEN_WIDTH, VSCREEN_HEIGHT/2 - 4);
            }
            else
            {
                scrX = 0; scrY = VSCREEN_HEIGHT/2;
                scrW = VSCREEN_WIDTH;
                scrH = VSCREEN_HEIGHT/2 + 4;
                gfx_clipping_set(0, VSCREEN_HEIGHT/2, VSCREEN_WIDTH, VSCREEN_HEIGHT/2 - 4);
            }
        }
    }

    game->tilemap->x += dx + centerX;
    game->tilemap->y += dy + centerY;
    gfx_render_tilemap(game->tilemap);
    game->tilemap->x -= dx + centerX;
    game->tilemap->y -= dy + centerY;

    // Draw each entity
    for(int i = 0; i < array_size(entities); i++)
    {
        Game_Entity *entity = &entities[i];
        if(entity->inUse)
        {
            GFX_Sprite sprite;
            memcpy(&sprite, &entity->sprite, sizeof(GFX_Sprite));
            sprite.x += dx + centerX + entity->x;
            sprite.y += dy + centerY + entity->y;

            gfx_render_sprite(&sprite);
        }
    }
    if(game->draw_player_gui)
    {
        (*game->draw_player_gui)(game, scrW, scrH, localPlayerIndex);
    }
    gfx_clipping_reset();
}

void game_draw(Game *game)
{
    Game_Entity *entities = array_new(array_size(game->entities), sizeof(Game_Entity));
    memcpy(entities, game->entities, array_size(game->entities) * sizeof(Game_Entity));
    qsort(entities, array_size(entities), sizeof(Game_Entity), _game_draw_sort_sprites);

    for(int i = 0; i < array_size(game->localPlayers); i++)
    {
        _game_draw_frame(game, i, game->localPlayers[i], entities);
    }

    array_delete(entities);
}

void game_delete(Game *game)
{
    gfx_tilemap_delete(game->tilemap);
    array_delete(game->players);
    array_delete(game->localPlayers);
    array_delete(game->entities);
    clock_delete(game->time);
    mem_free(game);
}
